package com.aote.rs;

import java.io.*;
import java.util.*;

import javax.annotation.PostConstruct;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

import com.aote.rs.mapper.WebException;
import com.browsesoft.*;
import com.browsesoft.dbtools.DBTools;
import com.browsesoft.resource.ResourceTool;
import com.browsesoft.resource.UniversalResourceEntity;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.JSONObject;

import com.browsesoft.resource.BasicResource;
import com.browsesoft.resource.Resource;
import com.browsesoft.user.Function;
import com.browsesoft.user.Organization;
import com.browsesoft.user.Role;
import com.browsesoft.user.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Path("data")
@Component
public class DataService {

	private static final Logger logger = LoggerFactory.getLogger(DataService.class);

	/**
	 * 更新新增数据的保存
	 * @param str 请求中的数据
	 * @return 是否保存成功
	 * @throws Exception 无
	 */
	@POST
	@Path("save")
	public String saveOrUpdate(String str) throws Exception {
		System.out.println("添加+++++"+str);
		JSONObject obj = (new JSONObject(str)).getJSONObject("data");
		
		// 判断保存的类型organization, function, role, user
		String type = obj.getString("resourcetype");
		System.out.println("type-->" + type);
		if(type.equals("organization")) { // 添加组织
			return saveOrganization(obj);
		}else if(type.equals("function")) { // 添加功能
			return saveFunction(obj);
		}else if(type.equals("role")) { // 添加角色
			return saveRole(obj);
		}else if(type.equals("user")) { // 添加用户
			return saveUser(obj);
		}else  		
			return saveOther(obj);
			//return "保存失败，未找到相关类型";
	}

	/**
	 * 调整资源位置，把sourceId对应的资源放到targetId下面
	 * @param sourceId 源id
	 * @param targetId 目标id
	 * @return 返回空串
	 */
	@POST
	@Path("adjust/{sourceid}/{targetid}")
	public String adjustPos(@PathParam("sourceid") String sourceId, @PathParam("targetid") String targetId) {
		Resource first = (Resource)EntityManager.getInstance().getObject(sourceId);
		Resource second = (Resource)EntityManager.getInstance().getObject(targetId);
		ResourceTool.add(first, second);
		return "";
	}

	/**
	 * 保存或更新用户
	 * @param obj 用户对象
	 * @throws Exception 无
	 */
	public String saveUser(JSONObject obj) throws Exception {
		//如果前台对象有id，从实体管理器中查找，并更新数据，如果无id，创建对象，加入实体管理器
		if (obj.getString("id").length() > 1) {
			BasicResource res = (BasicResource)EntityManager.getInstance().getObject(obj.getString("id"));
			res.getAttributes().put("name", obj.getString("name"));
			res.getAttributes().put("ename", obj.getString("ename"));
			res.getAttributes().put("touxiang", obj.getString("touxiang"));
			res.getAttributes().put("f_fengongsi", obj.getString("f_fengongsi"));
			res.getAttributes().put("f_fengongsinum", obj.getString("f_fengongsinum"));
			res.getAttributes().put("f_fapiaotaitu", obj.getString("f_fapiaotaitu"));
			res.getAttributes().put("f_fgsshuihao",obj.getString("f_fgsshuihao"));
			res.getAttributes().put("f_fgsdizhi",obj.getString("f_fgsdizhi"));
			res.getAttributes().put("f_fgsdianhua",obj.getString("f_fgsdianhua"));
			res.getAttributes().put("gonghao",obj.getString("gonghao"));
			res.getAttributes().put("f_invoicenum",obj.getString("f_invoicenum"));
			res.getAttributes().put("operpage",obj.getString("operpage"));
			res.getAttributes().put("f_bankname", obj.getString("f_bankname"));
			res.getAttributes().put("maxgassellnum", obj.getString("maxgassellnum"));
			res.getAttributes().put("myxgmax", obj.getString("myxgmax"));
			res.getAttributes().put("hemax", obj.getString("hemax"));
			res.getAttributes().put("gyxgmax", obj.getString("gyxgmax"));
			res.getAttributes().put("f_description", obj.getString("f_description"));
			if (!isSame(obj.getString("name"), obj.getString("parentid"), obj.getString("id"))) {
				return "更新失败，组织重名，请仔细检查";
			}
			res.update();
		}else {
			User user = new User();
			user.setTableName("t_user");
			// 前台传过来的字段
			this.mapPutJson(user.attributes, obj);
			// 固定字段
			user.attributes.put("entitytype", "t_user");
			user.attributes.put("tablename", "t_user");
			user.attributes.put("password", "1");
			user.attributes.put("f_icon", "tree_user");
			user.setTemplateName("useredit");
			user.setType(obj.getString("resourcetype"));
//			user.setParentID(obj.getString("parentid"));s
			if (!isSame(obj.getString("name"), obj.getString("parentid"), "")) {
				throw new WebException(705, "用户名重复，请仔细检查");
			}
			return insert(user, obj.getString("parentid"));
		}
		return "用户修改成功";
	}

	/**
	 * 保存或更新其它类型资源
	 * @param obj
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public String saveOther(JSONObject obj) throws Exception {
		if (obj.getString("id").length() > 1) {
			BasicResource res = (BasicResource)EntityManager.getInstance().getObject(obj.getString("id"));
			this.mapPutJson(res.getAttributes(), obj);
			res.update();
			return "修改成功";
		}else {
			UniversalResourceEntity res = new UniversalResourceEntity();
			// 前台传过来的字段
			this.mapPutJson(res.attributes, obj);
			String parentid = obj.getString("parentid");
			return insert(res, parentid);
		
		}
		
 	}

	/**
	 * 往hashtable中追加json里的内容, 不追加子节点
	 * @param ht
	 * @param json
     */
	private void mapPutJson(Hashtable ht, JSONObject json) {
		for (String key : json.keySet()) {
			Object value = json.get(key);
			// 不增加子节点
			if (key.equals("children")) {
				continue;
			}
			ht.put(key, json.get(key));
		}
	}

	/**
	 * 保存或更新组织结构
	 * @param obj
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public String saveOrganization(JSONObject obj) throws Exception {
		//如果前台对象有id，从实体管理器中查找，并更新数据，如果无id，创建对象，加入实体管理器
		if (obj.getString("id").length() > 1) {
			BasicResource res = (BasicResource)EntityManager.getInstance().getObject(obj.getString("id"));
			// 把前台传过来的内容全部放到组织中
			this.mapPutJson(res.getAttributes(), obj);

			if (!isSame(obj.getString("name"), obj.getString("parentid"), obj.getString("id"))) {
				return "更新失败，组织重名，请仔细检查";
			}
			res.update();
		}else {
			Organization org = new Organization();
			org.setTableName("t_organization");
			// 一下三个字段又前台传来
			org.attributes.put("name", obj.getString("name"));
			org.attributes.put("f_description", obj.getString("f_description"));
			org.attributes.put("number", obj.getString("number"));
			org.attributes.put("parentid", obj.getString("parentid"));
			// 一下为固定字段
			org.attributes.put("f_icon", "tree_org");
			org.setTemplateName("organizationedit");
			org.setType(obj.getString("resourcetype"));
			org.setParentID(obj.getString("parentid"));
			if (!isSame(obj.getString("name"), obj.getString("parentid"), "")) {
				return "组织重名，请仔细检查";
			}
			return insert(org, obj.getString("parentid"));
		}
		return "组织修改成功";
	}

	/**
	 * 保存添加角色
	 * @param obj
	 * @return
	 * @throws Exception 
	 */
	@SuppressWarnings("unchecked")
	public String saveRole(JSONObject obj) throws Exception {
		if (obj.getString("id").length() > 1) {
			BasicResource res = (BasicResource)EntityManager.getInstance().getObject(obj.getString("id"));
			res.getAttributes().put("name", obj.getString("name"));
			res.getAttributes().put("f_description", obj.getString("f_description"));
			if (!isSame(obj.getString("name"), obj.getString("parentid"), obj.getString("id"))) {
				return "更新失败，角色重名，请仔细检查";
			}
			res.update();
		}else {
			Role role = new Role();
			role.setTableName("t_role");
			// 一下三个字段又前台传来
			role.attributes.put("name", obj.getString("name"));
			role.attributes.put("f_description", obj.getString("f_description"));
			role.attributes.put("parentid", obj.getString("parentid"));
			// 一下为固定字段
			role.attributes.put("f_icon", "tree_role");
			role.setTemplateName("roleedit");
			role.setType(obj.getString("resourcetype"));
			role.setParentID(obj.getString("parentid"));
			if (!isSame(obj.getString("name"), obj.getString("parentid"), "")) {
				return "角色重名，请仔细检查";
			}
			return insert(role, obj.getString("parentid"));
		}
		return "角色保存成功";
	}
	@SuppressWarnings("unchecked")
	public String saveFunction(JSONObject obj) throws Exception {
		if (obj.getString("id").length() > 1) {
			BasicResource res = (BasicResource)EntityManager.getInstance().getObject(obj.getString("id"));
			res.getAttributes().put("name", obj.getString("name"));
			res.getAttributes().put("link", obj.getString("link"));
			res.getAttributes().put("navigate", obj.getString("navigate"));
			res.getAttributes().put("showmodel", obj.getString("showmodel"));
			res.getAttributes().put("icon", obj.getString("icon"));
			res.getAttributes().put("f_description", obj.getString("f_description"));
			if (!isSame(obj.getString("name"), obj.getString("parentid"), obj.getString("id"))) {
				return "更新失败，功能重名，请仔细检查";
			}
			res.update();
		}else {
			Function func = new Function();
			func.setTableName("t_function");
			func.setTemplateName("functionedit");
			func.setType("function");
			func.setParentID(obj.getString("parentid"));

			// 前台传过来的内容
			this.mapPutJson(func.attributes, obj);

			func.attributes.put("tablename", "t_function");
			func.attributes.put("linktype", "");
			func.attributes.put("f_icon", "");
			func.attributes.put("resourcetype", "function");
			func.attributes.put("pagenames", "公共通讯录维护模板");
			func.attributes.put("processnames", "发邮件流程");
			if (!isSame(obj.getString("name"), obj.getString("parentid"), "")) {
				return "功能重名，请仔细检查";
			}
			return insert(func, obj.getString("parentid"));
		}
		return "功能保存成功";
	}
	/**
	 * 为资源（组织机构，功能，角色，用户），增加一条记录，会产生id和selfid，传入资源不用添加id和selfid
	 * @param res 需要新增的资源
	 * @param parentid 父id
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private String insert(BasicResource res,String parentid) throws Exception {
		EntityManager entitymanager = (EntityManager) ManagerGroup
				.getManagerGroup().getManager("entity");
		Resource parent = (Resource) entitymanager
				.getObject(parentid);
		
		// 设置对象号
		String id = Integer.toString(SequenceFind.getID());
		res.attributes.put("id", id);
		id = Integer.toString(SequenceFind.getID());
		res.attributes.put("selfid", id);
		// 新数据增加
		res.insert();
		parent.addChild(res);
		parent.update();
		if (res instanceof Organization) {
			((Organization) res).setParentID(null);
		}else if(res instanceof Role) {
			((Role) res).setParentID(null);
		}else if(res instanceof Function) {
			((Function) res).setParentID(null);
		}
		res.update();
		return (String)res.getAttributes().get("id");
	}
	/**
	 * 为角色设置用户
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@POST
	@Path("setUser")
	public String setUser(String str) throws Exception {
		System.out.println(str);
		JSONObject obj = (new JSONObject(str)).getJSONObject("data");
		String roleid = obj.getString("roleid");
		System.out.println(roleid);
		org.json.JSONArray arr = obj.getJSONArray("ids");
		System.out.println(arr.toString());
		
		String strBack = "保存失败，未选择人员";
		Role role = (Role) EntityManager.getInstance().getObject(roleid);
		// 当前选中的集合
		LinkedList roles = new LinkedList();
		for(Object id : arr) {
//			System.out.println((String)id);
			Resource res = (Resource) EntityManager.getInstance().getObject((String)id);
			if (res instanceof User) {
				if (!role.getUsers().contains(res)) {
					role.add((User) res);
				}
				roles.add(res);
				strBack = "保存成功";
			}
		}
		// 将原本有，但本次没有选中的用户清除掉
		if (roles.size() > 0) {
			LinkedList list = role.getUsers();
			Iterator iter = list.iterator();
			while(iter.hasNext()) {
				User r = (User) iter.next();
				if(!roles.contains(r)) {
					role.remove(r);
				}
			}
		}
		return strBack;
	}
	/**
	 * 删除角色下的用户
	 * @param str 删除的用户信息，和角色id
	 * @throws Exception
	 */
	@POST
	@Path("deleteUser")
	public void deleteUser (String str) throws Exception {
		
		JSONObject obj = (new JSONObject(str)).getJSONObject("data");
		String roleid = obj.getString("roleid");
		
		org.json.JSONArray arr = obj.getJSONArray("ids");
		Role role = (Role) EntityManager.getInstance().getObject(roleid);
		
		for(Object row : arr) {
			String id = ((JSONObject)row).getString("id");
			Resource res = (Resource) EntityManager.getInstance().getObject((String)id);
			if (role.getUsers().contains(res)) {
				role.remove((User) res);
			}
		}
	}
	/**
	 * 通用的删除，所有角色，组织，用户，功能的删除统一使用
	 * @param str
	 * @return
	 * @throws Exception
	 */
	@POST
	@Path("delete")
	public String delete(String str) throws Exception {
		System.out.println("通用删除+++"+str);
		org.json.JSONArray array = (new JSONObject(str)).getJSONArray("data");
		for(Object obj: array) {
			BasicResource res = (BasicResource) EntityManager.getInstance().
					getObject(((JSONObject)obj).getString("id"));
			res.delete();
		}
		return "删除成功";
	}
	
	/**
	 * 
	 * @param name 资源名
	 * @param parentid 资源父id
	 * @param id 资源id
	 * @return 没有相同返回true，有相同返回false
	 * @throws Exception
	 */
	public boolean isSame(String name, String parentid, String id) throws Exception {
		EntityManager entitymanager = (EntityManager) ManagerGroup
				.getManagerGroup().getManager("entity");
		LinkedList v = new LinkedList();
		// 判断有无父组织
		if (parentid != null) {
			// 根据父ID取得父资源
			Resource p = (Resource) entitymanager.getObject(parentid);
			// 取出父的所有子
			v = Tools.iteratorToList(p.getChildren());
		}
		// 修改
		else {
			// 根据id取得资源
			Resource res = (Resource) entitymanager.getObject(id);
			if (res.getParent() != null) {
				// 取出所有子
				v = Tools.iteratorToList(res.getParent().getChildren());
			}
			// 是根组织只能修改
			else {
				return true;
			}
		}
		// 查找组织名，有相同 的return false
		for (int i = 0; i < v.size(); i++) {
			String temp = "";
			String selfId = "";
			if (v.get(i) instanceof Organization) {
				temp = (String) ((Organization) v.get(i)).getAttributes().get("name");
				selfId = (String) ((Organization) v.get(i)).getAttributes().get("id");
			}else if (v.get(i) instanceof Role) {
				temp = (String) ((Role) v.get(i)).getAttributes().get("name");
				selfId = (String) ((Role) v.get(i)).getAttributes().get("id");
			}else if (v.get(i) instanceof User) {
				temp = (String) ((User) v.get(i)).getAttributes().get("name");
				selfId = (String) ((User) v.get(i)).getAttributes().get("id");
			}else if (v.get(i) instanceof Function) {
				temp = (String) ((Function) v.get(i)).getAttributes().get("name");
				selfId = (String) ((Function) v.get(i)).getAttributes().get("id");
			}
			if (name.equals(temp)) {
				if (!id.equals(selfId)) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 构造函数后处理方法，DataService的构造函数在第一次访问其下Path时调用，紧接着调用@PostConstruct方法
	 * @throws IOException
	 */
	@PostConstruct
	public void init()throws Exception {
		// 首先调用Server加载过程
		Server.load();

		/* 根节点是否存在，这个从缓存中获取根节点，项目启动时，会从数据库加载缓存 */
		Resource root = EntityManager.getInstance().getRoot();
		/* 根节点已存在，不再进行处理，目前这样简单判断，不做差分 */
		if(root!=null) {
			logger.info("根节点已存在，不再进行配置文件处理");
			return;
		}

		logger.info("进入构造函数后处理方法，准备加载配置");
		String path = DataService.class.getResource("/ldap.json").getPath();
		logger.info("发现配置文件："+path);
		InputStream in = new FileInputStream(path);
		ObjectMapper mapper = new ObjectMapper();
		Map<String,Object> json = mapper.readValue(in, Map.class);
		handleRoot(json);
		// 处理其它单表数据
		handleOtherTables(json);
	}

	/**
	 * 处理其它需要初始化的单表
	 * @param obj
	 * @throws Exception
     */
	private void handleOtherTables(Map<String,Object> obj) throws Exception {
		List<Map<String, Object>> tables = (List<Map<String, Object>>) obj.get("othertable");
		for(Map<String, Object> table : tables) {
			String tableName = (String)table.get("tablename");
			Hashtable ht = new Hashtable();
			// 取得除表明外其它字段
			for(String name : table.keySet()) {
				if(!name.equals("tablename")) {
					ht.put(name, table.get(name));
				}
			}
			// 保存表中数据
			DBTools.insert(tableName, ht);
		}
	}

	/**
	 * 对根节点进行判断处理
	 */
	private void handleRoot(Map<String,Object> obj)throws Exception{
		obj = (Map<String, Object>) obj.get("resource");
		// 插入根节点
		UniversalResourceEntity res = new UniversalResourceEntity();
		String id = Integer.toString(SequenceFind.getID());
		res.attributes.put("id", id);
		id = Integer.toString(SequenceFind.getID());
		res.attributes.put("selfid", id);
		res.attributes.put("name",(String)obj.get("name"));
		res.attributes.put("position",(String)obj.get("position"));
		res.attributes.put("templatename",(String)obj.get("templatename"));
		res.attributes.put("tablename",(String)obj.get("tablename"));
		res.attributes.put("resourcetype",(String)obj.get("resourcetype"));
		res.attributes.put("position",(String)obj.get("position"));
		//res.attributes.put("parentid",(String)obj.get("parentid"));
		res.insert();
		logger.info("根节点保存成功");
			/* 递归处理根节点的子节点 */
		for(Object o:(List)obj.get("children")){
			recursiveHandle((Map)o,(String)res.getAttributes().get("id"));
		}
		// 给超级管理员设置根节点所有访问权限
		this.setSuperRight();
	}

	/**
	 * 设置超级管理员可以访问所有节点
	 */
	private void setSuperRight() throws Exception {
		BasicResource root = (BasicResource)EntityManager.getInstance().getRoot();
		// 得到超级管理员
		User user = (User)root.getAllChildrenByType("user").getFirst();
		JSONObject json = new JSONObject();
		json.put("parentid", "");
		json.put("resourceid", user.getID());
		json.put("byresourceid", root.getID());
		json.put("isinherit", "否");
		json.put("byisinherit", "是");
		json.put("resourceresult", "");
		json.put("byresourceresult", "");
		json.put("righttype", "");
		// 添加权限
		LicenseService service = new LicenseService();
		JSONObject data = new JSONObject();
		data.put("data", json);
		service.saveOrModify(data.toString());
	}

	/**
	 * 递归处理每个Map对象
	 * @param map：需要处理的Map对象，为一个json对象转换而来
	 * @param parentid：父资源对象的id
	 * @throws Exception
	 */
	private void recursiveHandle(Map<String,Object> map,String parentid)throws Exception {
		/* 设置id为空字符串，以保证对象为新插入 */
		map.put("id","");
		/* 将parentid设置到Map中，在save方法中使用 */
		map.put("parentid",parentid);
		String type = (String)map.get("resourcetype");
		JSONObject obj = new JSONObject(map);
		try{
			if(type.equals("organization")) { // 添加组织
				parentid = saveOrganization(obj);
			}else if(type.equals("function")) { // 添加功能
				parentid = saveFunction(obj);
			}else if(type.equals("role")) { // 添加角色
				parentid = saveRole(obj);
			}else if(type.equals("user")) { // 添加用户
				parentid = saveUser(obj);
			} else {	// 添加其它节点
				parentid = saveOther(obj);
			}
		}catch(Exception ex){
			logger.info("保存节点出错：");
			logger.info("出错节点为："+obj.toString());
			throw ex;
		}
		/* 递归处理根节点的子节点 */
		if(map.get("children")!=null){
			logger.info("即将处理指定节点的子节点："+parentid);
			for(Object o:(List)map.get("children")){
				recursiveHandle((Map)o,parentid);
			}
		}
	}
}